package com.xiashitech.agent.rule.usermatch.inst;

import cn.hutool.json.JSONUtil;
import com.google.auto.service.AutoService;
import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.constants.SpecialConfigString;
import com.xiashitech.agent.dto.UserRequest;
import com.xiashitech.agent.instrumentation.biz.userinfo.httpsession.SessionData;
import com.xiashitech.agent.rule.usermatch.base.UserInfoMatchRule;
import com.xiashitech.agent.utils.JsonUtil;
import com.xiashitech.agent.utils.TypeUtils;
import com.xiashitech.agent.utils.XSUtil;
import com.xiashitech.interfaces.agent.dto.AgentConfigDTO;
import ognl.Ognl;
import ognl.OgnlException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;

//@AutoService(UserInfoMatchRule.class)
public class XSHttpSessionUserMatch<REQUEST> implements UserInfoMatchRule<REQUEST> {
    @Override
    public UserRequest extractUserInfo(REQUEST request) {
        UserRequest userRequest = null;
        SessionData sessionData = new SessionData();
        String userSessionKey = null;
        String sessionKey = null ;
        Object value = new Object();
        String userIdPath = null;
        try {
            //if (request == null || !(request instanceof SessionData)) {
            if (request == null || (!(request instanceof SessionData) && !(request instanceof HttpServletRequest))) {
                System.out.println("###XSHttpSessionUserMacth  000");
                return UserRequest.builder().build();
            }
            Map<String, String> userSessionKeyMap = AgentConfigDTO.getConfig().getUserSessionKey();

            System.out.println("###XSHttpSessionUserMacth  001 userSessionKeyMap "+JsonUtil.convertObjectToString(userSessionKeyMap));

            if (userSessionKeyMap != null) {
                userSessionKey = userSessionKeyMap.get(StartConfig.getParamValueFromKey(StartConfig.systemId));
                System.out.println("###XSHttpSessionUserMacth  002 userSessionKey  "+userSessionKey);
            }
            userIdPath = XSUtil.getAgentConfigBySystemId(AgentConfigDTO.getConfig().getUseridpath());
            System.out.println("###XSHttpSessionUserMacth  004 userIdPath "+userIdPath);
            if (request instanceof SessionData) {
                sessionData = (SessionData) request;
                value = sessionData.getValue();
                sessionKey = sessionData.getKey();
                System.out.println("###XSHttpSessionUserMacth  004");
            } else if (request instanceof HttpServletRequest) {
                HttpServletRequest httpRequest  = (HttpServletRequest)request;
                HttpSession session = httpRequest.getSession();
                Enumeration<String> attrs = session.getAttributeNames();
                while (attrs.hasMoreElements()) {
                    // 获取session键值
                    sessionKey= attrs.nextElement().toString();
                    if(sessionKey.equals(userSessionKey)){
                        value = session.getAttribute(sessionKey);
                        break;
                    }
                    // 根据键值取session中的值

                }
                System.out.println("###XSHttpSessionUserMacth  002");
            }
            System.out.println("###XSHttpSessionUserMacth  003 sessionkey"+sessionKey+" sessionValue :"+JsonUtil.convertObjectToString(value));

            userRequest = UserRequest.builder().requestDate(String.valueOf(new Date().getTime())).build();
        } catch (Throwable e) {
            e.printStackTrace();
            StartConfig.throwableStackPrinter(e);
        }
        try {
            String configString  = SpecialConfigString.ALL_SESSION.getConfiString();
            if (SpecialConfigString.ALL_SESSION.getConfiString().equalsIgnoreCase(userSessionKey)) { // 表示把 session key 和 value 全部取出来
                if (value == null) {
                    userRequest.setUserid(sessionKey + ": null");
                } else {
                    if (sessionKey.startsWith("scopedTarget"))
                        userRequest.setUserid(sessionKey + "(" + value.getClass().getName() + "),scopedTarget: " + value);
                    else
                        // 在 xia_shi_all_session 配置下，转义 userIdPath 的配置，为不转 session 为字符串的 key 的名单(不区分达小写)，多个可用逗号/分号分隔
                        if (userIdPath == null || userIdPath.isEmpty() || userIdPath.toLowerCase().contains(sessionKey.toLowerCase()))
                            userRequest.setUserid(sessionKey + "(" + value.getClass().getName() + "): " + value);
                        else
                            userRequest.setUserid(sessionKey + "(" + value.getClass().getName() + "): " + JsonUtil.convertObjectToString(value));
                }
                return userRequest;
            }

            if (value == null) return userRequest;
            if (userSessionKey.equalsIgnoreCase(sessionKey) && "de.hybris.platform.commerceservices.jalo.CommerceJaloSession".equalsIgnoreCase(value.getClass().getName())) {
                // userSessionKey 配为：jalosession， useridpath：配为 USERID: （注意要有英文冒号），字符串格式被认为：(Compler/SessionID,USERID:b123)
                if (userIdPath == null || userIdPath.length() == 0)
                    userIdPath = "USERID:"; // 设置一个默认值，避免空指针
                String sessionValueStr = value.toString();
                int pos = sessionValueStr.indexOf(userIdPath);
                if (pos > 0) {
                    String userId = sessionValueStr.substring(pos + userIdPath.length(), sessionValueStr.length() - 1);
                    userRequest.setUserid(userId);
                } else {
                    userRequest.setUserid("[useridpath:" + userIdPath + "]:" + sessionValueStr);
                }
                return userRequest;
            } else {
                // 当值为 json 字符串时，先转为 Map 对象
                if (value.getClass() == String.class) {
                    if (JsonUtil.isJson((String) value)) {
                        value = JsonUtil.convertStringToObject((String) value, Map.class);
                    }
                }
                // 如果是基本类型，直接设置，不需再 Ognl 读取
                if (TypeUtils.isPrimitiveOrWrap(value.getClass())) {
                    userRequest.setUserid(String.valueOf(value));
                    return userRequest;
                }
                if (XSUtil.isEmpty(userIdPath)) {
                    return userRequest;
                }

                String userId = null;
                try {
                    userId = String.valueOf(Ognl.getValue(userIdPath, value));
                    System.out.println("###XSHttpSessionUserMacth  007 userId"+userId+" userIdPath "+userIdPath+" sessionValue: "+JsonUtil.convertObjectToString(value));

                } catch (OgnlException e) {
                    StartConfig.throwableStackPrinter(e);
                }
                //在 Webspere + IBM JDK8 环境下 OGNL 取值表现灵异，时好时坏。这里打个补丁。
                if (userId == null) {
                    String jsonStr = JsonUtil.convertObjectToString(value);
                    userId = XSUtil.getJsonNodeValueByPath(jsonStr, userIdPath);
                }
                System.out.println("###XSHttpSessionUserMacth 008 userId "+userId);
                userRequest.setUserid(userId);
            }
        } catch (Throwable e) {
            e.printStackTrace();
            StartConfig.throwableStackPrinter(e);
        }

        return userRequest;
    }


    @Override
    public Integer getOrder() {
        return 6;
    }
}
